package com.atguigu.gulimall.ware.listener;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.constant.OrderConstant;
import com.atguigu.common.to.mq.OrderTo;
import com.atguigu.common.to.mq.StockDetailTo;
import com.atguigu.common.to.mq.StockLockedTo;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.ware.entity.WareOrderTaskDetailEntity;
import com.atguigu.gulimall.ware.entity.WareOrderTaskEntity;
import com.atguigu.gulimall.ware.feign.OrderFeignService;
import com.atguigu.gulimall.ware.service.WareOrderTaskDetailService;
import com.atguigu.gulimall.ware.service.WareOrderTaskService;
import com.atguigu.gulimall.ware.service.WareSkuService;
import com.atguigu.gulimall.ware.vo.OrderVo;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * 库存解锁监听器
 *
 * @author LaiSanShan
 * @date 2021-09-10
 */
@Slf4j
@RabbitListener(queues = "stock.release.stock.queue")
@Service
public class StockReleaseListener {

    @Autowired
    WareSkuService wareSkuService;

    @Autowired
    OrderFeignService orderFeignService;

    @Autowired
    WareOrderTaskDetailService wareOrderTaskDetailService;

    @Autowired
    WareOrderTaskService wareOrderTaskService;

    /**
     * 库存自动解锁
     * 1.下订单成功，库存锁定成功，接下来的业务调用失败导致回滚解锁，有库存工作单id和详情id记录
     * 2.下订单失败，因为库存锁定失败
     *
     * @param to  库存锁定消息
     * @param msg 消息
     */
    @RabbitHandler
    public void handleStockLockedRelease(StockLockedTo to, Message msg, Channel channel) throws IOException {
        try {
            System.out.println("收到解锁库存消息");
            // 库存工作单id
            Long id = to.getId();
            // 库存工作单详情
            StockDetailTo detailTo = to.getDetailTo();
            Long skuId = detailTo.getSkuId();
            Long detailToId = detailTo.getId();

            // 根据工作单详情id查询记录
            WareOrderTaskDetailEntity taskDetailEntity = wareOrderTaskDetailService.getById(detailToId);
            if (taskDetailEntity == null) {
                // 说明库存没锁定成功，无需回滚
                // 删除消息
                channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
            } else {
                // 说明库存锁定成功了，可能需要解锁
                // 检查订单是否成功
                WareOrderTaskEntity taskEntity = wareOrderTaskService.getById(id);
                String orderSn = taskEntity.getOrderSn();
                R r = orderFeignService.queryStatusByOrderSn(orderSn);
                if (r.getCode() == 0) {
                    OrderVo orderVo = r.getData(new TypeReference<OrderVo>() {
                    });
                    // 订单不存在||订单被取消了，解锁库存
                    if (orderVo == null || orderVo.getStatus() == OrderConstant.OrderStatusEnum.CANCLED.getCode()) {
                        // 订单工作单锁定状态才解锁
                        if (taskDetailEntity.getLockStatus() == 1) {
                            wareSkuService.unLockStock(skuId, detailTo.getWareId(), detailTo.getSkuNum(), detailToId);
                            taskDetailEntity.setLockStatus(2);
                            wareOrderTaskDetailService.updateById(taskDetailEntity);
                        }
                        // 删除消息
                        channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
                    }
                } else {
                    // 拒绝，重新放回到队列
                    channel.basicReject(msg.getMessageProperties().getDeliveryTag(), false);
                }
            }
        } catch (Exception e) {
            // 拒绝，重新放回到队列
            System.out.println("错误。。。" + e.getMessage());
            channel.basicReject(msg.getMessageProperties().getDeliveryTag(), false);
        }

    }

    /**
     * 库存主动解锁
     *
     * @param orderTo 订单实体
     * @param msg     消息
     * @param channel 通道
     */
    @RabbitHandler
    public void handleOrderCloseRelease(OrderTo orderTo, Message msg, Channel channel) throws IOException {
        System.out.println("订单关闭准备解锁库存。。。");
        try {
            wareSkuService.unLockStock(orderTo);
            channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            channel.basicReject(msg.getMessageProperties().getDeliveryTag(), false);
        }
    }

}
